
def gentic_algorithm(objective, n_bits, n_iter, n_pop, r_cross, r_mut):
    #initial population of random bistring
    pop = [[np.random.randint(0,2) for j in range(n_bits)] for i in range(n_pop)]
    #keep track of best solution
    best, best_eval = 0, objective(pop[0])
    #enumerate generations
    for gen in range(n_iter):
        #evaluate all condidates in the population
        scores = [objective(c) for c in pop]
        #check for new best solution
        for i in range(n_pop):
            if scores[i] < best_eval:
                best, best_eval = pop[i], scores[i]
                print(">",gen,"new best f",pop[i], "=",scores[i])
        #select parents
        selected = [selection(pop, scores) for i in range(n_pop)]
        #create the next generation
        children = list()
        for i in range(0,n_pop-1, 2):
            #get selected parents in pairs
            p1, p2 = selected[i], selected[i+1]
            #crossover and mutation
            for c in crossover(p1, p2, r_cross):
                #mutation
                mutation(c, r_mut)
                #store for next generation
                children.append(c)
        #replace population
        pop = children
    return [best, best_eval]


